#include<iostream>
#include<string>
using namespace std;

//int main()
//{
//    string s1("hello world");
//    // 这里s1是左值，调用的是拷贝构造
//    string s2(s1);
//    // 这里我们把s1 move处理以后, 会被当成右值，调用移动构造
//    // 但是这里要注意，一般是不要这样用的，因为我们会发现s1的
//    // 资源被转移给了s3，s1被置空了。
//    move(s1);
//    string s3(s1);
//    cout<<"s1:"<<s1<<endl;
//    cout<<"s2:"<<s2<<endl;
//    cout<<"s3:"<<s3<<endl;
//    return 0;
//}

//void Fun(int &x){ cout << "左值引用" << endl; }
//void Fun(const int &x){ cout << "const 左值引用" << endl; }
//void Fun(int &&x){ cout << "右值引用" << endl; }
//void Fun(const int &&x){ cout << "const 右值引用" << endl; }
//// 模板中的&&不代表右值引用，而是万能引用，其既能接收左值又能接收右值。
//// 模板的万能引用只是提供了能够接收同时接收左值引用和右值引用的能力，
//// 但是引用类型的唯一作用就是限制了接收的类型，后续使用中都退化成了左值，
//// 我们希望能够在传递过程中保持它的左值或者右值的属性, 就需要用我们下面学习的完美转发
//template<typename T>
//void PerfectForward(T&& t)//一定记住，只有函数模版这里才是万能引用，不然不是
//{
//    //Fun(t);//这样是不行的，因为这我们前说的，如果接受的值是右值，右值一旦被右值引用引用后，就会变成左值，所以我们需要如果接受的值是右值，右值一旦被右值引用引用后，保持右值属性，但是我们这里不能使用move，因为万一接受就是一个左值，你给人家强行转为右值是不对的。我们需要保持它原本的属性，这就需要完美转发。 Fun(forward<T>(t))
//    //保持实参属性
//    Fun(forward<T>(t));
//}
//int main()
//{
//    PerfectForward(10); // 右值
//    int a;
//    PerfectForward(a); // 左值
//    PerfectForward(std::move(a)); // 右值
//    const int b = 8;
//    PerfectForward(b); // const 左值
//    PerfectForward(std::move(b)); // const 右值
//    return 0;
//}

void _ShowList()
{
    cout<<endl;
}

template <class T,class ...Args>
void _ShowList(const T& val,Args... args)
{
    cout<<val<<"    ";
    _ShowList(args...);
}

template <class ...Args>
void ShowList(Args... args)
{
    _ShowList(args...);
}

int main()
{
    ShowList(1);
    ShowList(1,2);
    ShowList(1,2,3);
    ShowList(1,2.2,'x');
}
